#include "stdafx.h"
#include "AniSystem.h"
#include "Utility.h"
#include "MemTrack.h"

namespace bs
{
	const int MAX_ELEMENT_ID = 10000;

	AniSystem::AniSystem() : lastId(0)
	{
	}

	AniSystem::~AniSystem()
	{
		while(!this->workings.empty())
		{
			SAFE_DELETE(this->workings.back());
			this->workings.pop_back();
		}

		while(!this->waitings.empty())
		{
			SAFE_DELETE(this->waitings.back());
			this->waitings.pop_back();
		}
	}

	void AniSystem::Update(size_t elapse, float speedFactor)
	{
		if(this->workings.empty())
			return;

		for(std::vector<AniElement*>::iterator itr=this->workings.begin();
			itr!=this->workings.end(); ++itr)
		{
			(*itr)->object->Update((int)elapse, speedFactor);
		}

		this->FlushWorkingList();

		if(this->workings.empty())
		{
			for(std::set<IAniSystemListener*>::iterator itr=this->listeners.begin();
				itr!=this->listeners.end(); ++itr)
			{
				(*itr)->OnAniEnd();
			}
		}
	}

	void AniSystem::Render(HDC dc)
	{
		for(std::vector<AniElement*>::reverse_iterator itr=this->workings.rbegin();
			itr!=this->workings.rend(); ++itr)
		{
			(*itr)->object->Draw(dc);
		}
	}

	int AniSystem::AddAniElement( AniObject* ani, int preId /*= -1*/, bool owned /*= true*/ )
	{
		if(!ani)
			return -1;

		this->lastId %= MAX_ELEMENT_ID;
		++ this->lastId;

		AniElement* ele = new AniElement(this->lastId, ani, preId, owned);
		if(preId<0 || !this->FindWorkingElement(preId))
		{
			this->InsertToWorkingList(ele);
		}
		else
		{
			this->waitings.push_back(ele);
		}

		return this->lastId;
	}

	AniSystem::AniElement* AniSystem::FindWorkingElement(int id)
	{
		for(std::vector<AniElement*>::iterator itr=this->workings.begin();
			itr!=this->workings.end(); ++itr)
		{
			if((*itr)->id == id)
			{
				return *itr;
			}
		}

		return NULL;
	}

	void AniSystem::InsertToWorkingList(AniElement* ele)
	{
		if(this->workings.empty())
		{
			for(std::set<IAniSystemListener*>::iterator itr=this->listeners.begin();
				itr!=this->listeners.end(); ++itr)
			{
				(*itr)->OnAniBegin();
			}
		}

		ele->object->Start();

		for(std::vector<AniElement*>::iterator itr=this->workings.begin();
			itr!=this->workings.end(); ++itr)
		{
			if(*(ele->object) >= *((*itr)->object))
			{
				this->workings.insert(itr, ele);
				return;
			}
		}

		this->workings.push_back(ele);
	}

	void AniSystem::FlushWorkingList()
	{
		std::vector<int> endIds;
		for(std::vector<AniElement*>::iterator itr=this->workings.begin();
			itr!=this->workings.end(); )
		{
			if(!(*itr)->object->IsPlaying())
			{
				endIds.push_back((*itr)->id);
				SAFE_DELETE(*itr);        
				itr = this->workings.erase(itr);
			}
			else
			{
				++ itr;
			}
		}

		while(!endIds.empty() && !this->waitings.empty())
		{
			int id = endIds.back();
			endIds.pop_back();

			for(std::vector<AniElement*>::iterator itr=this->waitings.begin();
				itr!=this->waitings.end(); )
			{
				if((*itr)->preEleId == id)
				{
					this->InsertToWorkingList(*itr);
					itr = this->waitings.erase(itr);
				}
				else
				{
					++ itr;
				}
			}
		}
	}
}
